home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-04 | 23.1 KB | 859 lines | [TEXT/KAHL] |
- /***************************************************** IMPLEMENTATION
- DATE: 9/20/93
- AUTHOR: Eric R. Rosé
-
- CLASS: CPPWindow
-
- SUPERCLASS: CPPObjectList
-
- This C++ class manages a Macintosh window; it is subclassed
- from an object list so that it can keep track of all of the
- objects within the window
-
- ********************************************************************/
-
- #include <CPPWindow.h>
- #include <math.h>
- #include <MathTools.h>
- #include <CPPWindowManager.h>
- #include <CPPVisualObject.h>
- #include <Commands.h>
-
-
- /*-----------------------------------------------------------------*/
- /*--------------------------- GLOBALS -----------------------------*/
- /*-----------------------------------------------------------------*/
-
- CPPWindow *gTheModalWindow;
- pascal Boolean ModalFilterProc (DialogPtr theDlg,
- EventRecord *theEvent,
- short *itemHit );
- void DoStdOKButton (CPPWindow *theWindow);
- void DoStdCancelButton (CPPWindow *theWindow);
-
- /*-----------------------------------------------------------------*/
- /*------------------------ PUBLIC METHODS -------------------------*/
- /*-----------------------------------------------------------------*/
-
- void DoStdCancelButton (CPPWindow *theWindow)
- {
- if (theWindow)
- theWindow->EndModalWindow (FALSE);
- }
-
- /*-----------------------------------------------------------------*/
-
- void DoStdOKButton (CPPWindow *theWindow)
- {
- if (theWindow)
- theWindow->EndModalWindow (TRUE);
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPWindow::CPPWindow (CPPWindowManager *theManager,
- Rect *bounds, Str255 title, Boolean isVisible,
- short windowKind, Boolean hasGoAway, short refCon,
- Boolean isModal, Boolean isColor,
- short windowFont, short windowSize)
- /* create a window based on the passed in parameters */
- {
- if (isColor)
- this->theWindow = NewCWindow(NULL, bounds, title, isVisible,
- windowKind, (WindowPtr)-1,
- hasGoAway, refCon);
- else
- this->theWindow = NewWindow(NULL, bounds, title, isVisible,
- windowKind, (WindowPtr)-1,
- hasGoAway, refCon);
-
- if (this->theWindow)
- MakeCPPWindow (theManager, windowFont, windowSize);
- else
- this->WisVisible = this->WisActive = FALSE;
-
- this->isCWindow = isColor;
- this->isModalWindow = isModal;
- this->modalResult = FALSE;
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPWindow::CPPWindow (CPPWindowManager *theManager, short ResID,
- Boolean isModal, Boolean isColor,
- short windowFont, short windowSize)
- /* get a window based on an existing resource template */
- {
-
- if (isColor)
- this->theWindow = GetNewCWindow(ResID, NULL, (WindowPtr)-1);
- else
- this->theWindow = GetNewWindow(ResID, NULL, (WindowPtr)-1);
-
- if (this->theWindow)
- MakeCPPWindow (theManager, windowFont, windowSize);
- else
- this->WisVisible = this->WisActive = FALSE;
-
- this->isCWindow = isColor;
- this->isModalWindow = isModal;
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPWindow::~CPPWindow (void)
- {
- CPPVisualObject *TempObject = NULL;
-
- // first, hide our window; this will take care of
- // updates in the window list
- this->Close();
-
- // tell the windowmanager it doesn't have to worry about us
- if (this->ourManager)
- this->ourManager->StopManagingWindow(this);
-
- // dispose of all the objects which we contain
- DeleteItems(TRUE);
-
- // finally, dispose of our own data
- if (this->theWindow)
- DisposeWindow(this->theWindow);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::Close (void)
- /* perform a close operation by simply hiding the window */
- {
- if (this->theWindow && ((WindowPeek)this->theWindow)->goAwayFlag)
- this->Show(FALSE);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::Open (void)
- /* perform a close operation by simply showing a hidden window */
- {
- this->Show(TRUE);
- }
-
- /*-----------------------------------------------------------------*/
-
- char *CPPWindow::ClassName (void)
- {
- return "CPPWindow";
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::EndModalWindow (Boolean endResult)
- /* tell the modal window to dismiss itself; return the specified */
- /* value as a result */
- {
- this->modalResult = endResult;
- this->modalDone = TRUE;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoModalWindow (void)
- /* treat the window as if it were a modal window */
- {
- EventRecord theEvent;
- CPPWindow *theWindowObject;
- short eventMask;
-
- // assume the user will cancel
- this->modalResult = FALSE;
-
- // set up the event mask to only accept modal dialog events
- eventMask = mDownMask + mUpMask + keyDownMask + keyUpMask +
- autoKeyMask + updateMask + activMask + networkMask;
-
- // set the modal window completion variable
- this->modalDone = FALSE;
-
- while (!this->modalDone)
- {
- if (WaitNextEvent(eventMask, &theEvent, 0, NULL))
- this->Do(&theEvent);
- else
- this->DoIdle();
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::SetMinMaxSize (short minWidth, short minHeight,
- short maxWidth, short maxHeight)
- {
- this->minWidth = minWidth;
- this->minHeight = minHeight;
- this->maxWidth = maxWidth;
- this->maxHeight = maxHeight;
-
- // let the window manager maintain the data it needs
- // for zoomable windows;
- switch (GetWVariant(this->theWindow)) {
- case zoomNoGrow :
- case zoomDocProc :
- SetZoomedOutSize (maxWidth, maxHeight);
- break;
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::SetZoomedOutSize (short maxWidth, short maxHeight)
- {
- WStateData **hWSD;
- Rect zRect;
-
- // set the 'zoomed out' size of the window to the maximum size
- if (theWindow)
- {
- hWSD = (WStateData **)((WindowPeek)theWindow)->dataHandle;
- zRect = (**hWSD).stdState;
- zRect.bottom = Min (zRect.top + maxHeight, zRect.bottom);
- zRect.right = Min (zRect.left + maxWidth, zRect.right);
- (**hWSD).stdState = zRect;
- this->maxWidth = (zRect.right - zRect.left);
- this->maxHeight = (zRect.bottom - zRect.top);
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::DoCommand (short commandID)
- /* the default method sends the command to the target of the */
- /* window. */
- /* SUBCLASS SHOULD OVERRIDE */
- {
- CPPVisualObject *theTarget = GetTarget();
-
- if (theTarget)
- return theTarget->DoCommand(commandID);
- else
- return FALSE;
- }
-
- /*-----------------------------------------------------------------*/
-
- WindowPtr CPPWindow::GetWindow (void)
- {
- return this->theWindow;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::Update (EventRecord *theEvent)
- {
- WindowPtr uWindow = (WindowPtr)theEvent->message;
- GrafPtr savePort;
-
- if (uWindow == this->theWindow)
- {
- // prepare the window to be drawn into
- BeginUpdate (this->theWindow);
- GetPort (&savePort);
- SetPort (this->theWindow);
-
- // call the user's draw routine
- this->DoUserUpdate();
-
- // draw the grow icon if necessary
- switch (GetWVariant(this->theWindow)) {
- case documentProc :
- case zoomDocProc :
- DrawGrowIcon(this->theWindow);
- break;
- }
-
- // restore the drawing environment
- SetPort (savePort);
- EndUpdate (this->theWindow);
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::Show (Boolean doShowWindow)
- /* make the window visible or invisible */
- {
- if (this->theWindow)
- {
- if (doShowWindow)
- {
- ShowWindow (this->theWindow);
- SelectWindow (this->theWindow);
- this->ourManager->ActivateWindowObject (this);
- }
- else
- {
- HideWindow(this->theWindow);
- this->ourManager->DeactivateWindowObject (this);
- }
-
- this->WisVisible = doShowWindow;
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::RefreshItemStates()
- /* this routine is called whenever an event occurs so that */
- /* the window can check to see if any of the objects in it */
- /* should be enabled/disabled, etc. For example, if a button */
- /* should only be active when certain conditions are true, */
- /* you could use this routine to activate/deactivate it */
- /* SUBCLASS SHOULD OVERRIDE */
- {
-
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::Do (EventRecord *theEvent)
- /* handle the passed event; return TRUE if you handle it, */
- /* FALSE if you dont */
- {
- GrafPtr savePort;
- Boolean result = FALSE;
- WindowPtr EventWindow;
-
- if (!theWindow) return FALSE;
-
- // check to see if the event happened in our window
- switch (theEvent->what) {
- case updateEvt :
- case activateEvt :
- EventWindow = (WindowPtr)theEvent->message;
- break;
- case keyDown :
- case autoKey :
- EventWindow = FrontWindow();
- break;
- default :
- FindWindow (theEvent->where, &EventWindow);
- break;
- }
-
- if (this->theWindow != EventWindow)
- return FALSE;
-
- // now that we know the event happened in our window,
- // handle it
- GetPort(&savePort);
- SetPort(this->theWindow);
-
- switch (theEvent->what) {
- case nullEvent :
- if (this->WisActive)
- {
- DoUserIdle ();
- result = TRUE;
- }
- break;
- case mouseDown :
- result = this->DoClick(theEvent);
- break;
- case keyDown :
- case autoKey :
- result = this->DoUserKey (theEvent);
- break;
- case updateEvt:
- this->Update(theEvent);
- result = TRUE;
- break;
- case activateEvt :
- if (ODD(theEvent->modifiers))
- this->ourManager->ActivateWindowObject(this);
- else
- this->ourManager->DeactivateWindowObject(this);
- result = TRUE;
- break;
- }
-
- RefreshItemStates();
-
- SetPort(savePort);
- return result;
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::DoClick (EventRecord *theEvent)
- /* react to a click in the object's window by bringing it */
- /* forward (if necessary) and performing the appropriate action */
- /* return TRUE if the click was in our window, FALSE otherwise */
- {
- short part;
- WindowPtr hitWindow;
-
- part = FindWindow(theEvent->where, &hitWindow);
- if (hitWindow == this->theWindow)
- {
- if (!this->WisActive)
- SelectWindow(this->theWindow);
-
- switch (part) {
- case inDrag :
- DoDragClick (theEvent);
- break;
- case inGrow :
- DoGrowClick (theEvent);
- break;
- case inZoomIn :
- DoZoomClick (theEvent, part);
- break;
- case inZoomOut :
- DoZoomClick (theEvent, part);
- break;
- case inGoAway :
- DoGoAwayClick (theEvent);
- break;
- case inContent :
- DoContentClick (theEvent);
- break;
- default :
- return FALSE;
- break;
- }
- return TRUE;
- }
-
- return FALSE;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoIdle (void)
- {
- DoUserIdle ();
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::MakePreviousTarget (void)
- /* make the 'targetable' and visible object preceeding the */
- /* current one into the target for the window; return TRUE if */
- /* the target changes */
- {
- CPPVisualObject *oldTarget = this->currentTarget,
- *newTarget = NULL,
- *tempObject = NULL;
- long itemsToCheck = GetNumItems(),
- itemsInList = itemsToCheck,
- current = FindIndex(currentTarget);
-
- // proceed through the list from the current element,
- // looking for the next one which can be made the target
- while (itemsToCheck)
- {
- current--;
- if (!current)
- current = itemsInList;
- tempObject = (CPPVisualObject *)((*this)[current]);
- if (tempObject && tempObject->IsVisible() &&
- tempObject->CanBeMadeTarget())
- {
- newTarget = tempObject;
- break;
- }
- itemsToCheck--;
- }
-
- // if there is another object targetable, target it
- if ((newTarget) && (newTarget != oldTarget))
- {
- MakeTarget(newTarget);
- return TRUE;
- }
- else
- return FALSE;
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::MakeNextTarget ()
- /* make the next 'targetable' and visible object into the target */
- /* for the window; return TRUE if the target changed */
- {
- CPPVisualObject *oldTarget = this->currentTarget,
- *newTarget = NULL,
- *tempObject = NULL;
- long itemsToCheck = GetNumItems(),
- itemsInList = itemsToCheck,
- current = FindIndex(currentTarget);
-
- // proceed through the list from the current element,
- // looking for the next one which can be made the target
- while (itemsToCheck)
- {
- current = ((current + 1) % (itemsInList+1));
- current += (current) ? 0 : 1;
- tempObject = (CPPVisualObject *)((*this)[current]);
- if (tempObject && tempObject->IsVisible() &&
- tempObject->CanBeMadeTarget())
- {
- newTarget = tempObject;
- break;
- }
- itemsToCheck--;
- }
-
- // if there is another object targetable, target it
- if ((newTarget) && (newTarget != oldTarget))
- {
- MakeTarget(newTarget);
- return TRUE;
- }
- else
- return FALSE;
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPVisualObject *CPPWindow::GetTarget (void)
- /* return the current target in the window */
- {
- return this->currentTarget;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::MakeTarget (CPPVisualObject *theObject)
- /* The target is the object which should receive key events. */
- /* call this routine to change the target object in the window */
- /* if 'theObject' = NULL, assume the user wants to deactivate */
- /* the current target without assigning another */
- {
- if (theObject == NULL)
- {
- if (this->currentTarget)
- this->currentTarget->TargetHilite(FALSE);
- this->currentTarget = NULL;
- }
- else
- if (FindIndex(theObject))
- {
- if ((theObject != this->currentTarget) &&
- theObject->CanBeMadeTarget() && theObject->IsVisible())
- {
- if (this->currentTarget)
- this->currentTarget->TargetHilite (FALSE);
- this->currentTarget = theObject;
- this->currentTarget->TargetHilite (TRUE);
- }
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::IsColorWindow (void)
- /* return TRUE if this is a color window */
- {
- return this->isCWindow;
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::IsModalWindow (void)
- /* return TRUE if this is a modal or movable modal window */
- {
- return this->isModalWindow;
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::WindowVisible (void)
- /* return whether or not the window is visible */
- {
- return this->WisVisible;
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::WindowActive (void)
- /* return whether or not the window is active */
- {
- return this->WisActive;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::StartManagingObject (CPPVisualObject *theObject)
- /* add a visual object to the list of objects we know about */
- {
- if (theObject)
- this->AppendItem (theObject);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::StopManagingObject (CPPVisualObject *theObject)
- /* remove a visual object from the list of objects we know about */
- {
- DeleteItem(theObject, FALSE);
- }
-
- /*-----------------------------------------------------------------*/
- /*---------------------- PROTECTED METHODS ------------------------*/
- /*-----------------------------------------------------------------*/
-
- pascal Boolean ModalFilterProc (DialogPtr theDlg,
- EventRecord *theEvent,
- short *itemHit)
- /* this class method is used as the modal dialog filter; it */
- /* passes the event it receives on to the window object stored */
- /* in gTheModalWindow */
- {
- if (gTheModalWindow)
- return (gTheModalWindow->Do (theEvent));
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::Activate (void)
- /* do the necessary bookkeeping to keep track of the window's state */
- /* and pass the message on to all the window's contents */
- {
- for (long i = 1; i<= GetNumItems(); i++)
- {
- CPPVisualObject *theObject = (CPPVisualObject *)((*this)[i]);
- if (theObject)
- theObject->Activate(TRUE);
- }
-
- if (this->theWindow)
- this->WisActive = TRUE;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::Deactivate (void)
- /* do the necessary bookkeeping to keep track of the window's state */
- {
- for (long i = 1; i<= GetNumItems(); i++)
- {
- CPPVisualObject *theObject = (CPPVisualObject *)((*this)[i]);
- if (theObject)
- theObject->Activate(FALSE);
- }
-
- if (this->theWindow)
- this->WisActive = FALSE;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoUserChangeSize (short newWidth, short newHeight)
- /* instance specific handler for changing the size of the window */
- /* You might use this to move the window's scrollbars, if it has */
- /* any */
- /* SUBCLASS SHOULD OVERRIDE */
- {
-
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoUserClick (EventRecord *theEvent)
- /* instance specific handler for clicking in the window */
- /* this handler tests each item and passes the click to the */
- /* one where it occurred */
- /* SUBCLASS SHOULD OVERRIDE */
- {
- for (long i = 1; i<= GetNumItems(); i++)
- {
- CPPVisualObject *theObject = (CPPVisualObject *)((*this)[i]);
- if (theObject && theObject->InContent(theEvent->where))
- {
- MakeTarget(theObject);
- if (theObject->DoClick(theEvent))
- break;
- }
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoUserUpdate (void)
- /* instance specific handler for drawing the window's contents */
- /* this handler goes through each item and draws it */
- /* SUBCLASS SHOULD OVERRIDE */
- {
- for (long i = 1; i<= GetNumItems(); i++)
- {
- CPPVisualObject *theObject = (CPPVisualObject *)((*this)[i]);
- if (theObject)
- theObject->Draw();
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoUserIdle (void)
- /* instance specific handler for idling when the window is */
- /* the frontmost window - hand it to the current target object */
- /* SUBCLASS SHOULD OVERRIDE */
- {
- if (currentTarget)
- currentTarget->DoIdle();
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPWindow::DoUserKey (EventRecord *theEvent)
- /* instance specific handler for handling a keypress - hand */
- /* it off to the current target object. */
- /* return TRUE if we handled the key, FALSE otherwise */
- /* SUBCLASS SHOULD OVERRIDE */
- {
- if (currentTarget)
- return currentTarget->DoKey(theEvent->message & charCodeMask,
- theEvent->modifiers, theEvent->what);
- else
- return FALSE;
- }
-
- /*-----------------------------------------------------------------*/
- /*----------------------- PRIVATE METHODS -------------------------*/
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoDragClick (EventRecord *theEvent)
- /* drag a window around the screen */
- {
- RgnHandle deskRegion = GetGrayRgn();
-
- if (this->theWindow)
- DragWindow(this->theWindow, theEvent->where,
- &((**deskRegion).rgnBBox));
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoZoomClick (EventRecord *theEvent, short thePart)
- {
- Point myPt;
- Rect tempRect;
-
- if (this->theWindow)
- {
- SetPort(this->theWindow);
- myPt = theEvent->where;
- GlobalToLocal(&myPt);
- if (TrackBox(this->theWindow, myPt, thePart))
- {
- ZoomWindow (this->theWindow, thePart, TRUE);
-
- // erase the contents of the window
- SetRect (&tempRect, 0, 0, 32000, 32000);
- EraseRect(&tempRect);
- InvalRect(&tempRect);
-
- // let the user know the window changed size
- tempRect = this->theWindow->portRect;
- DoUserChangeSize (tempRect.right - tempRect.left,
- tempRect.bottom - tempRect.top);
-
- }
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoGoAwayClick (EventRecord *theEvent)
- {
- if (this->theWindow)
- {
- if (TrackGoAway (this->theWindow, theEvent->where))
- this->Close();
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoGrowClick (EventRecord *theEvent)
- {
- Point myPt;
- Rect tempRect, oldRect;
- long mResult;
- WStateData **hWSD;
-
- if (this->theWindow)
- {
- SetPort(this->theWindow);
- myPt = theEvent->where;
- GlobalToLocal(&myPt);
-
- oldRect = this->theWindow->portRect;
-
- // Set the minimum and maximum sizes for the drag
- SetRect (&tempRect, this->minWidth, this->minHeight,
- this->maxWidth, this->maxHeight);
-
- // Drag, then change the window size
- mResult = GrowWindow (this->theWindow, theEvent->where, &tempRect);
- SizeWindow (this->theWindow, LoWord(mResult),
- HiWord(mResult), TRUE);
-
- // erase the contents of the window
- SetRect (&tempRect, 0, 0, 32000, 32000);
- EraseRect (&tempRect);
- InvalRect (&tempRect);
-
- //let the user know the window changed size
- tempRect = this->theWindow->portRect;
- DoUserChangeSize (tempRect.right - tempRect.left,
- tempRect.bottom - tempRect.top);
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::DoContentClick (EventRecord *theEvent)
- {
- if (this->theWindow)
- {
- if (!this->WisActive)
- this->ourManager->ActivateWindowObject(this);
- SetPort(this->theWindow);
- this->DoUserClick (theEvent);
- }
- }
-
- /*-----------------------------------------------------------------*/
- /*----------------------- PRIVATE METHODS -------------------------*/
- /*-----------------------------------------------------------------*/
-
- void CPPWindow::MakeCPPWindow (CPPWindowManager *theManager,
- short windowFont, short windowSize)
- /* the common part of both constructors */
- {
- GrafPtr savePort;
-
- this->minWidth = 70;
- this->minHeight = 70;
-
- this->currentTarget = NULL;
- // remember which window manager is ours, and add ourself to
- // its list
- this->ourManager = theManager;
- this->ourManager->DeactivateWindowObject(this->ourManager->FrontWindowObject());
- this->ourManager->StartManagingWindow(this);
- this->WisActive = FALSE;
- this->WisVisible = ((WindowPeek)this->theWindow)->visible;
- this->ourManager->ActivateWindowObject(this);
- SelectWindow (this->theWindow);
-
- // set the font and font size for the window
- GetPort (&savePort);
- SetPort (this->theWindow);
- TextFont (windowFont);
- TextSize (windowSize);
- SetPort (savePort);
-
- }
-